#include <vector>
#include <mutex>
#include <semaphore.h>
using namespace std;

template<class T>
class RingQueue
{
    #define DEFAULT_CAPACITY 5
public:
    RingQueue(size_t capacity = DEFAULT_CAPACITY):_capacity(capacity), _rear(0), _front(0)
    {
        _q.resize(_capacity);
        sem_init(&_pro_sem, 0, _capacity);
        sem_init(&_com_sem, 0, 0);
    }

    ~RingQueue()
    {
        sem_destroy(&_pro_sem);
        sem_destroy(&_com_sem);
    }

    void Push(const T& val)
    {
        P(&_pro_sem);
        {
            unique_lock<mutex> lck(_pro_mutex);
            _q[_rear++] = val;
            _rear %= _capacity;
        }        
        V(&_com_sem);
    }

    void Pop(T* val)
    {
        P(&_com_sem);
        {
            unique_lock<mutex> lck(_com_mutex);
            *val = _q[_front++];
            _front %= _capacity;
        }
        V(&_pro_sem);
    }

private:
    void P(sem_t* sem)
    {
        sem_wait(sem);
    }

    void V(sem_t* sem)
    {
        sem_post(sem);
    }
private:
    vector<T> _q;
    size_t _capacity;
    sem_t _pro_sem;
    sem_t _com_sem;
    size_t _front;
    size_t _rear;
    mutex _pro_mutex;
    mutex _com_mutex;
};